package com.zhongli.devplatform.service.impl.live;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.live.v20180801.LiveClient;
import com.tencentcloudapi.live.v20180801.models.*;
import com.zhongli.devplatform.component.live.LiveProperties;
import com.zhongli.devplatform.bean.SecurityHelper;
import com.zhongli.devplatform.dto.LiveDTO;
import com.zhongli.devplatform.dto.LiveParams;
import com.zhongli.devplatform.exception.ServiceException;
import com.zhongli.devplatform.mapper.live.ReadLiveMapper;
import com.zhongli.devplatform.mapper.live.ReadLiveRoomMapper;
import com.zhongli.devplatform.mapper.view.ViewUserMapper;
import com.zhongli.devplatform.po.live.ReadLivePO;
import com.zhongli.devplatform.po.live.ReadLiveRoomPO;
import com.zhongli.devplatform.po.view.ViewUserPO;
import com.zhongli.devplatform.service.imp.live.ReadLiveRoomService;
import com.zhongli.devplatform.service.imp.live.TencentLive;
import com.zhongli.devplatform.utils.LiveUtils;
import com.zhongli.devplatform.vo.live.LiveCloseVO;
import com.zhongli.devplatform.vo.live.LiveOpenVO;
import com.zhongli.devplatform.vo.live.LiveVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 直播房间表(ReadLiveRoom)表服务实现类
 *
 * @author aiyuan
 * @since 2020-08-07 11:31:12
 */
@Service
public class ReadLiveRoomServiceImpl extends ServiceImpl<ReadLiveRoomMapper, ReadLiveRoomPO> implements ReadLiveRoomService {

    @Resource
    public ReadLiveRoomMapper liveRoomMapper;

    @Resource
    public ReadLiveMapper liveMapper;

    @Resource
    public ViewUserMapper viewUserMapper;

    @Resource
    public LiveProperties liveProperties;

    @Resource
    public TencentLive tencentLive;

    /**
     * 创建直播间 老师若是没有房间号 先创建房间
     * @param liveDTO 房间封面 描述标题
     * @return 返回直播推流地址
     */
    @Override
    public LiveOpenVO createLive(LiveDTO liveDTO) {
        Integer currentUserId = SecurityHelper.getCurrentUserId();
        ViewUserPO userPO = viewUserMapper.selectOne(new QueryWrapper<ViewUserPO>().eq("user_id",currentUserId));
        ReadLiveRoomPO liveRoomPO = liveRoomMapper.selectOne(new QueryWrapper<ReadLiveRoomPO>()
                .eq("teacher_id", currentUserId));

        String pushUrl = tencentLive.getPushUrl();
        String pushStream = tencentLive.getPushStream(currentUserId.toString());
        String pullFlvUrl = tencentLive.getFLVPlayUrl(currentUserId.toString());
        String pullRtmpUrl = tencentLive.getRTMPPlayUrl(currentUserId.toString());

        ReadLivePO LivePO = new ReadLivePO();//新的直播记录
        ReadLiveRoomPO readLiveRoomPO;
        if (liveRoomPO == null) {
            readLiveRoomPO = new ReadLiveRoomPO();
            readLiveRoomPO.setTeacherId(currentUserId);
            readLiveRoomPO.setStreamName(currentUserId.toString());
            readLiveRoomPO.setPushUrl(pushUrl);
            readLiveRoomPO.setPullUrl(pullFlvUrl);
            liveRoomMapper.insert(readLiveRoomPO);
            LivePO.setRoomId(readLiveRoomPO.getId());
        }else {
            ReadLivePO readLivePO = liveMapper.selectOne(new QueryWrapper<ReadLivePO>()
                    .eq("room_id", liveRoomPO.getId()).eq("is_online", true));
            if (readLivePO != null) {
                throw new ServiceException("创建的直播间正在直播！");
            }
            LivePO.setRoomId(liveRoomPO.getId());
        }
        LivePO.setCoverUrl(liveDTO.getCoverUrl());
        LivePO.setLiveTitle(liveDTO.getLiveTitle());
        LivePO.setStartTime(new Date());
        LivePO.setNickName(userPO.getNickName());
        LivePO.setIsOnline(true);


        liveMapper.insert(LivePO);

        LiveOpenVO liveOpenVO = new LiveOpenVO();
        liveOpenVO.setPushStream(pushStream);
        liveOpenVO.setPushUrl(pushUrl+pushStream);
        liveOpenVO.setPullFLVUrl(pullFlvUrl);
        liveOpenVO.setPullRTMPUrl(pullRtmpUrl);

        return liveOpenVO;
    }

    @Override
    public List<LiveVO> getAllOnlineLive() {
        try{
            LiveClient client = LiveUtils.getLiveClient();
            String params1 = "{}";
            DescribeLiveStreamOnlineListRequest onlineListRequest = DescribeLiveStreamOnlineListRequest.fromJsonString(params1, DescribeLiveStreamOnlineListRequest.class);
            DescribeLiveStreamOnlineListResponse onlineList = client.DescribeLiveStreamOnlineList(onlineListRequest);

            /*SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date = format.format(new Date());
            String params2 = "{\"QueryTime\":\""+date+"\"}";
            DescribeAllStreamPlayInfoListRequest playInfoListRequest = DescribeAllStreamPlayInfoListRequest.fromJsonString(params2, DescribeAllStreamPlayInfoListRequest.class);
            DescribeAllStreamPlayInfoListResponse playInfo = client.DescribeAllStreamPlayInfoList(playInfoListRequest);
            MonitorStreamPlayInfo[] dataInfoList = playInfo.getDataInfoList();*/

            ArrayList<LiveVO> data = new ArrayList<>();
            StreamOnlineInfo[] onlineInfo = onlineList.getOnlineInfo();
            for (StreamOnlineInfo info : onlineInfo) {
                String streamName = info.getStreamName();
                ReadLiveRoomPO liveRoomPO = liveRoomMapper.selectOne(new QueryWrapper<ReadLiveRoomPO>().eq("stream_name", streamName));
                ReadLivePO LivePO = liveMapper.selectOne(new QueryWrapper<ReadLivePO>()
                        .eq("room_id", liveRoomPO.getId())
                        .eq("is_online", true));
                LiveVO liveVO = new LiveVO();
                liveVO.setCoverUrl(LivePO.getCoverUrl());
                liveVO.setLiveTitle(LivePO.getLiveTitle());
                liveVO.setRTMPPlayUrl(tencentLive.getRTMPPlayUrl(streamName));
                liveVO.setFLVPlayUrl(tencentLive.getFLVPlayUrl(streamName));
                liveVO.setGetHLSPlayUrl(tencentLive.getHLSPlayUrl(streamName));
                //查询直播时在线人数
                LiveParams params = new LiveParams();
                params.setStreamName(streamName);
                params.setPlayDomain(liveProperties.getPlayDomain());
                //params.setAppName(info.getAppName());
                setDate(params);//设置查询时间
                Integer watchCount = getWatchCount(params);
                liveVO.setWatchCount(watchCount);
                data.add(liveVO);
            }
            return data;
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
            return new ArrayList<>();
        }

    }

    /**
     * 关闭直播间
     * @return 直播信息
     */
    @Override
    public LiveCloseVO closeLiveBroadcast() {
        Integer currentUserId = SecurityHelper.getCurrentUserId();
        ViewUserPO userPO = viewUserMapper.selectById(currentUserId);
        ReadLiveRoomPO liveRoomPO = liveRoomMapper.selectOne(new QueryWrapper<ReadLiveRoomPO>()
                .eq("teacher_id", currentUserId));
        Integer roomId = liveRoomPO.getId();
        ReadLivePO readLivePO = liveMapper.selectOne(new QueryWrapper<ReadLivePO>()
                .eq("room_id", roomId).eq("is_online", true));
        //查询关闭直播时在线人数
        LiveParams params = new LiveParams();
        params.setStreamName(liveRoomPO.getStreamName());
        params.setPlayDomain(liveProperties.getPlayDomain());
        params.setAppName("live");
        setDate(params);//设置查询时间
        Integer watchCount = getWatchCount(params);
        readLivePO.setWatchNum(watchCount);
        readLivePO.setEndTime(new Date());
        String minutes = getMinutes(readLivePO.getStartTime(), readLivePO.getEndTime());//直播时长
        readLivePO.setDuration(minutes);
        readLivePO.setIsOnline(false);
        readLivePO.setReviewNum(null);//评论数  待处理

        liveMapper.updateById(readLivePO);//修改直播记录
        params.setDomainName(liveProperties.getPushDomain());//推流域名
        params.setPlayDomain(null);//清空参数
        params.setStartTime(null);//清空参数
        params.setEndTime(null);//清空参数
        disconnectLive(params);//断开直播流

        LiveCloseVO liveCloseVO = new LiveCloseVO();
        liveCloseVO.setWatchCount(watchCount);
        liveCloseVO.setAccountNum(userPO.getAccountNum());
        liveCloseVO.setNickName(userPO.getNickName());
        liveCloseVO.setHeadImgUrl(liveCloseVO.getHeadImgUrl());
        liveCloseVO.setLikes(null);//@TODO 点赞数 待处理
        liveCloseVO.setDuration(minutes);
        return liveCloseVO;
    }

    //获取在线人数
    private Integer getWatchCount(LiveParams liveParams){
        LiveClient client = LiveUtils.getLiveClient();
        String params = JSON.toJSONString(liveParams);
        DescribeStreamPlayInfoListRequest req = DescribeStreamPlayInfoListRequest.fromJsonString(params, DescribeStreamPlayInfoListRequest.class);
        Integer online = null;
        try {
            DescribeStreamPlayInfoListResponse resp = client.DescribeStreamPlayInfoList(req);
            DayStreamPlayInfo[] dataInfoList = resp.getDataInfoList();
            online = Math.toIntExact(dataInfoList[0].getOnline());
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
        }
        return online;
    }

    //计算相差分钟数
    private String getMinutes(Date startTime,Date endTime){
        long from = startTime.getTime();
        long to = endTime.getTime();
        int minutes = (int) ((to - from)/(1000 * 60));
        return minutes + "分钟";
    }

    //断开直播流
    private void disconnectLive(LiveParams liveParams){
        LiveClient client = LiveUtils.getLiveClient();
        String params = JSON.toJSONString(liveParams);
        DropLiveStreamRequest req = DropLiveStreamRequest.fromJsonString(params, DropLiveStreamRequest.class);
        try {
            client.DropLiveStream(req);
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
        }
    }

    private void setDate(LiveParams params){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        params.setStartTime(format.format(new Date(new Date().getTime() - 6 * 60 * 1000)));
        params.setEndTime(format.format(new Date(new Date().getTime() - 5 * 60 * 1000)));
    }

}
